import axios from 'axios'
import history from '../router/history'
import {message} from 'antd'
import settings from '../../settings'
import Loading from '../components/loading/Loading'

const axiosInstance = axios.create({});
const ajax = {};

ajax.request = config => request('request', null, null, config);
ajax.get = (url, config) => request('get', url, null, config);
ajax.delete = (url, config) => request('delete', url, null, config);
ajax.head = (url, config) => request('head', url, null, config);
ajax.options = (url, config) => request('options', url, null, config);
ajax.post = (url, data, config) => request('post', url, data, config);
ajax.put = (url, data, config) => request('put', url, data, config);
ajax.patch = (url, data, config) => request('patch', url, data, config);

ajax.all = axios.all;
ajax.spread = axios.spread;

class ResponseHandler {
  constructor (promise) {
    this.promise = promise
  }

  then (handler) {
    this.promise
      .then((res) => {
        handler(res);
        if (this.finallyHandler) {
          this.finallyHandler._isHandled = true;
          this.finallyHandler()
        }
      })
      .catch(e => {
        console.log(e);
        if (this.catchHandler) {
          this.catchHandler(e);
        }
        if (e && e.message === 'Network Error') {
          message.error('网络错误！')
        } else {
          message.error('系统错误！')
        }
        if (this.finallyHandler && !this.finallyHandler._isHandled) {
          this.finallyHandler();
        }
      });
    return this
  }

  catch (handler) {
    this.catchHandler = handler;
    return this
  }

  finally (handler) {
    this.finallyHandler = handler;
  }
}

function request (reqMethod, url, data, config) {
  try {
    let req;
    switch (reqMethod) {
      case 'request':
        req = axiosInstance[reqMethod](config);
        break;
      case 'get':
      case 'delete':
      case 'head':
      case 'options':
        req = axiosInstance[reqMethod](url, config);
        break;
      case 'post':
      case 'put':
      case 'patch':
        req = axiosInstance[reqMethod](url, data, config);
        break;
      default:
        message.error('请求方式不支持！');
        return
    }
    return new ResponseHandler(req)
  } catch (e) {
    return new ResponseHandler(Promise.reject(e))
  }
}

let clock = null;
let reqCount = 0;
const SHOW_LOADING_DELAY = 500;

function reqEnd () {
  reqCount--;
  if (reqCount < 1) {
    clearTimeout(clock);
    Loading.hide();
  }
}

function reqStart () {
  if (reqCount === 0 && clock) {
    clock = setTimeout(() => {
      Loading.show()
    }, SHOW_LOADING_DELAY);
  }
  reqCount++;
}

const regs = [];
if (settings.isProxy) {
  Object.keys(settings.apiUrls).forEach((key) => {
    let reg = new RegExp(key);
    regs.push({reg, value: settings.apiUrls[key]})
  })
}

axiosInstance.interceptors.request.use((config) => {
  reqStart();

  // 前端proxy
  let url = config.url;
  for (let i = 0; i < regs.length; i++) {
    let item = regs[i];
    if (item.reg.test(url)) {
      config.url = url.replace(item.reg, item.value);
      break
    }
  }
  // 解决get请求缓存问题
  if (config.method && config.method.toLowerCase() === 'get') {
    config.url = config.url + '?t_t=' + new Date().getTime()
  }
  config.headers.token = window.sessionStorage.getItem('apptoken');

  return config
}, (err) => {
  reqEnd();

  return Promise.reject(err)
});

axiosInstance.interceptors.response.use((res) => {
  reqEnd();

  if (res && res.status === 200) {
    res = res.data;
    if (res && res.code === 301) {
      window.sessionStorage.removeItem('apptoken');
      history.replace('/login')
    }
    if (res && res.code !== 0) {
      message.error(res.data || res.message || '操作失败或发生错误！')
    }
  }
  return res
}, (err) => {
  reqEnd();

  return Promise.reject(err)
});

export default ajax
